﻿using System;
using System.Collections.Generic;
using Microsoft.SharePoint.WebPartPages;
using System.Runtime.InteropServices;
using System.Web.UI;
using Microsoft.SharePoint;
using System.IO;
using System.Linq;
using System.Xml;

namespace WebPartHub.SharePoint.WebPartHub
{
    /// <summary>
    /// TODO
    /// </summary>
    [System.Runtime.InteropServices.Guid("4942d93f-581a-4cf8-b158-7194c1f17b58")]
    public class WebPartHubGallerySource : WebPartGallerySourceBase
    {
        private const string WebPartHubUrl = "http://intranet/admin"; // TODO: remove hardcoding
        private const string WebPartCategory = "Custom"; // TODO: support multiple categories? Remove hardcoding

        public WebPartHubGallerySource(Page page)
            : base(page)
        {
        }

        protected override WebPartGalleryItemBase[] GetItemsCore()
        {
            List<WebPartGalleryItemBase> items = new List<WebPartGalleryItemBase>();

            // running elevated under system token context
            using (SPSite hubSite = new SPSite(WebPartHubUrl, GetSystemToken(SPContext.Current.Site)))
            {
                // TODO: exclude wpg if category/webparts already exists
                // TODO: check safe controls on webapp
                SPList webPartsGallery = hubSite.GetCatalog(SPListTemplateType.WebPartCatalog);

                SPListItemCollection webParts = webPartsGallery.Items;
                // TODO: get group from feature property
                List<SPListItem> customWebParts = (from SPListItem wp in webParts where wp["Group"].ToString() == WebPartCategory select wp).ToList();

                foreach (SPListItem webPart in customWebParts)
                {
                    XmlReader xmlReader = new XmlTextReader(webPart.File.OpenBinaryStream());
                    XmlDocument doc = new XmlDocument();
                    doc.Load(xmlReader);
                    WebPartGalleryItemBase item = new WebPartHubGalleryItem(this, base.Page, doc, webPart.File.Url, WebPartCategory);
                    if (item != null)
                    {
                        items.Add(item);
                    }
                }
            }

            return items.ToArray();


        }

        internal SPUserToken GetSystemToken(SPSite site)
        {
            SPUserToken token = null;
            bool tempCADE = site.CatchAccessDeniedException;
            try
            {
                site.CatchAccessDeniedException = false;
                token = site.SystemAccount.UserToken;
            }
            catch (UnauthorizedAccessException)
            {
                SPSecurity.RunWithElevatedPrivileges(() =>
                {
                    using (SPSite elevSite = new SPSite(site.ID))
                        token = elevSite.SystemAccount.UserToken;
                });
            }
            finally
            {
                site.CatchAccessDeniedException = tempCADE;
            }
            return token;
        }
    }
}
